/*
* Entourage
* Copyright 2011 INF532@Galatasaray University & Vincent Labatut 
* 
* This file is part of Entourage.
* 
* Entourage is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* 
* Entourage is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* 
* You should have received a copy of the GNU General Public License
* along with Entourage. If not, see <http://www.gnu.org/licenses/>.
* 
*/

package com.appspot.entourage.freebasechecker;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import com.appspot.entourage.freebasechecker.Freebase;
import com.freebase.json.JSON;

import static com.freebase.json.JSON.o;
import static com.freebase.json.JSON.a;

import com.appspot.entourage.common.*;

/**
 * This class is used to check if a link label's text is really a person or not
 * by querying the freebase server with the Search API or MQL Read API according
 * to the link label url. It also has a caching mechanism to not requery the
 * freebase server for the same key.
 * @author Berk PELENK <bpelenk@beengames.com>
 * @version 1
 * @see Person
 * @see NamedLink
 *
 */
public class FreebaseChecker {
	
	/** this field represents cached data as search key, search result */
	public static HashMap<String, Person> cachedPersons = new HashMap<String,Person>();
	
	/**
	 * This method is used to query the Freebase database for a string. If the
	 * link label url is a wikipedia url, we first try to query the person via
	 * his/her wikipedia url from the Freebase database using Freebase's MQL
	 * Read API. If no answer is found or the url is not a wiki url, we query 
	 * the Freebase server with the search key using Freebase's Search API.
	 * @param nl Link label which contains the searched person's data
	 * @return Searched person data if found, null if not.
	 * @author Berk PELENK <bpelenk@beengames.com>
	 * @see Person
	 * @see NamedLink
	 */
	public static Person checkNamedLink(NamedLink nl)
	{
		// Cache system
		
		Person cachedpers = cachedPersons.get(nl.getText());
		if(cachedpers != null)
			return new Person(cachedpers.getFullName(), cachedpers.getGuid(), nl.getUrl());
		
		
		try
		{
			URI uri = new URI(nl.getUrl());
			String path = uri.getPath();
			Freebase freebase = Freebase.getFreebase();
			Person pers = null;
			
			if(uri.getHost().contains(".wikipedia.org"))
			{
				String lang = uri.getHost().substring(0, uri.getHost().indexOf('.'));
				path = path.substring(path.lastIndexOf("/")+1);
				path = UnicodeConverter.mqlkey_quote(path);
		
		
				JSON mqlreadquery = a(o(
						  "id", null,
						  "guid", null,
						  "name", null,
						  "type", "/people/person",
						  "key", a(o(
								  "type", "/type/key",
								    "namespace", "/wikipedia/"+lang,
								    "value", path
						  ))
						));
		  

				JSON result = freebase.mqlread(mqlreadquery);
				
				if(result.get("result").array().size() > 0)
					pers = new Person(result.get("result").get(0).get("name").string(), result.get("result").get(0).get("guid").string(), nl.getUrl());
			}
			
			if(pers == null)
			{
				
				JSON options = o(
						  "type", "/people/person",
						  "type_strict", "all",
						  "limit", "1"
						);
				
				JSON result = freebase.search(nl.getText(), options);
				
				if(result.get("result").array().size() > 0)
					pers = new Person(result.get("result").get(0).get("name").string(), result.get("result").get(0).get("guid").string(), nl.getUrl());
			}
			
			if(pers != null)
				cachedPersons.put(nl.getText(), pers);

			return pers;
		}
		catch(Exception e)
		{
			System.out.println(e.getMessage());
			
			return null;
		}
	}
	
	/**
	 * This method takes an array of link labels and returns the resulting
	 * person list by querying the Freebase server for each link label.
	 * @param links An array of link labels to be queried one by one 
	 * @return Elements of the links array as Person object.
	 * @author Berk PELENK <bpelenk@beengames.com>
	 * @see checkNamedLink
	 * @see Person
	 * @see NamedLink
	 */
	public static List<Person> checkNamedLinks(List<NamedLink> links)
	{
		List<Person> persons = new ArrayList<Person>();
		for(NamedLink nl : links)
		{
		Person pers = checkNamedLink(nl);
		if(pers != null)
			persons.add(pers);
		}
		
		return persons;
	}
}
